package com.da.landlord;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.annotation.Resource;

import org.apache.commons.collections.map.ListOrderedMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.spring.GenericService;
import com.ra.landlord.FeeAddition;
import com.ra.landlord.FeeAdditionRecord;
import com.ra.landlord.FeeAdditionService;
import com.ra.landlord.FeeRule;
import com.ra.landlord.FeeRuleCfg;
import com.ra.landlord.FeeRuleCfgCalc;
import com.ra.landlord.FeeRuleCfgDesc;
import com.ra.landlord.FeeRuleCfgDescService;
import com.ra.landlord.LandlordUser;
import com.ra.landlord.LandlordUserService;
import com.ra.landlord.Meter;
import com.ra.landlord.RoomService;
import com.ra.landlord.constant.FeeRuleType;
import com.ra.system.Version;
import com.ra.util.DateTimeUtil;

/**
 * 抄表服务
 * 
 * @author colin
 * @date 2015年5月15日
 */
@Service
public class DaMeterService {

	private static final Log logger = LogFactory.getLog(DaOwnerService.class);

	@Resource
	private GenericService genericService;

	@Resource
	private LandlordUserService landlordUserService;

	@Resource
	private RoomService roomService;

	@Resource
	private FeeAdditionService feeAdditionService;

	@Resource
	private FeeRuleCfgDescService feeRuleCfgDescService;

	@Resource
	private DaChargeItemService daChargeItemService;

	@Resource
	private DaRoomMeterItemService daRoomMeterItemService;

	@Rest(type = "search")
	public List<FeeRuleCfgDesc> searchMeterCategory() {
		FeeRuleCfgDesc feeRuleCfgDesc = new FeeRuleCfgDesc();
		feeRuleCfgDesc.setType(FeeRuleType.meter);
		feeRuleCfgDesc.setStatus(Version.STATUS_VALID);

		String strShort = "isShare";
		String strOrderBy = "ASC";
		PageInfo<FeeRuleCfgDesc> pageInfo = this.genericService.search(feeRuleCfgDesc, 0, 100, strShort, strOrderBy,
				false, null, null, true, false);

		return pageInfo.getData();
	}

	@Transactional
	@Rest(type = "add")
	public DaMeter add(DaMeter model) {
		BigDecimal price = genericService.load(model.getFeeRule()).getFeeRuleCfg().getFeeRuleCfgCalc().getPrice();
		model.setPrice(price);
		model.setReader(landlordUserService.getLoginUser());
		model.setCheckTime(Calendar.getInstance().getTime());

		DaFeeRule feeRule = genericService.load(model.getFeeRule());
		LandlordUser landlordUser = feeRule.getSuite().getLandlordUser();
		model.setLandlordUser(landlordUser.getOwnerUser());

		return genericService.add(model);
	}

	/**
	 * 添加抄表记录
	 * 
	 * @param models
	 * @return
	 * @throws ParseException
	 */
	@Rest(type = "add")
	@Transactional
	public List<DaMeter> addMeters(List<DaMeter> models) {
		List<DaMeter> meters = new ArrayList<DaMeter>();
		Calendar calendar = Calendar.getInstance();
		for (DaMeter model : models) {
			DaFeeRule feeRule = genericService.load(model.getFeeRule());
			if (feeRule == null) {
				continue;
			}
			DaMeter emptyMeter = feeRule.getMeter(0);
			if (emptyMeter == null) {
				emptyMeter = genericService.load(DaMeter.class, 0);
			}
			DaChargeItem chargeItemExample = new DaChargeItem();
			chargeItemExample.setMeter1(emptyMeter);
			chargeItemExample.setMeter2(emptyMeter);
			chargeItemExample.setFeeRuleCfg(feeRule.getFeeRuleCfg());
			DaRoom dbRoom = feeRule.getRoom();
			if (dbRoom == null) {
				dbRoom = feeRule.getSuite().getRooms().get(0);
			}
			chargeItemExample.setChargeBillRecord(daChargeItemService.getOrGenerateChargeBillRecord(dbRoom));
			chargeItemExample.setChargeType(DaChargeItem.CHARGE_TYPE_METER);
			DaChargeItem needDeleteChargeItem = genericService.searchByModel(chargeItemExample, Condition.DEFAULT).getData(0);
			if (needDeleteChargeItem != null && !DaChargeItem.STATUS_PAID.equals(needDeleteChargeItem.getStatus())) {
				needDeleteChargeItem.getChargeBillRecord().getChargeItems().remove(needDeleteChargeItem);
			}
			
			List<DaMeter> dbMeters = feeRule.getMeters();
			Date dbMaxTime = null;
			if (dbMeters != null && dbMeters.size() > 0) {
				dbMaxTime = dbMeters.get(0).getCheckTime();
			}

			BigDecimal price = feeRule.getFeeRuleCfg().getFeeRuleCfgCalc().getPrice();
			model.setPrice(price.setScale(2, BigDecimal.ROUND_HALF_UP));
			model.setReader(landlordUserService.getLoginUser());
			// 抄表时间，取系统时间
			Date modelCheckTime = model.getCheckTime();
			if (modelCheckTime != null) {
				Calendar modelCalendar = Calendar.getInstance();
				modelCalendar.setTime(modelCheckTime);
				calendar.set(Calendar.YEAR, modelCalendar.get(Calendar.YEAR));
				calendar.set(Calendar.MONTH, modelCalendar.get(Calendar.MONTH));
				calendar.set(Calendar.DATE, modelCalendar.get(Calendar.DATE));
			}

			if (dbMaxTime != null) {
				if (dbMaxTime.after(calendar.getTime())) {
					calendar.setTime(new Date(dbMaxTime.getTime() + 1000));
				}
			}

			model.setCheckTime(calendar.getTime());
			LandlordUser landlordUser = landlordUserService.getLoginUser();
			model.setLandlordUser(landlordUser.getOwnerUser());
			DaMeter meter = genericService.merge(model);
			genericService.refresh(feeRule);

			createSubMeterChargeItems(feeRule, meter);
			meters.add(meter);
		}
		return meters;
	}

	// TODO:准备废弃
	private void createMeterChargeItems(DaFeeRule feeRule, DaMeter meter) {
		// suite有两次抄表记录，才能调用产生费用的接口
		// suite有合约，且合约内的抄表至少有1条数据才抄表
		DaSuite suite = feeRule.getSuite();
		List<DaRoom> rooms = suite.getRentRooms();
		if (rooms != null && rooms.size() > 0) {
			Date agreementBeginDate = null;
			// 获取该suite所有room的合约中最早的开始日期
			for (DaRoom daRoom : rooms) {
				DaAgreement agreement = daRoom.getAgreement();
				if (agreement != null) {
					if (agreementBeginDate != null) {
						if (agreementBeginDate.compareTo(agreement.getRentBeginDate()) > 0) {
							agreementBeginDate = agreement.getRentBeginDate();
						}
					} else {
						agreementBeginDate = agreement.getRentBeginDate();
					}
				}
			}
			if (agreementBeginDate != null) {
				feeRule = genericService.load(feeRule);
				List<DaMeter> tempMeters = feeRule.getMeters();
				/*
				 * QLInfo qlInfo = new QLInfo("from " + DaMeter.class.getName()
				 * + " a where a.feeRule.id=? order by a.checkTime desc", false,
				 * feeRule.getId()); List<DaMeter> tempMeters
				 * =genericService.searchByQl(qlInfo).getData(); //保证取到数据库最新的
				 * feeRule.setMeters(tempMeters);//如果FeeRule与meter配置有级联操作，，
				 * 请不要这么做！！！
				 */
				if (tempMeters != null && tempMeters.size() > 1) {
					DaMeter earlyMeter = tempMeters.get(1);
					if (agreementBeginDate.compareTo(earlyMeter.getCheckTime()) < 0) {
						try {
							daChargeItemService.createMeterChargeItems(feeRule);
						} catch (ParseException e) {
							logger.error("抄表产生费用时发生异常!meter.id:" + meter.getId(), e);
						}
					}
				}
			}
		}
	}

	private void createSubMeterChargeItems(DaFeeRule feeRule, DaMeter meter) {
		DaSuite suite = feeRule.getSuite();
		if (suite == null) {
			suite = feeRule.getRoom().getSuite();
		}
		// 处理整租
		if (suite.getRentType() != 1) {
			if (suite.getRentRooms().size() == 0) {
				return;
			}
			DaRoom room = suite.getRentRooms().get(0);
			if (room.getAgreement() != null && room.getAgreement().getRentBeginDate() != null
					&& feeRule.getMeters().size() > 1) {
				DaMeter prevMeter = feeRule.getMeters().get(1);
				DaMeter thisMeter = feeRule.getMeters().get(0);
				if ((prevMeter.getCount().compareTo(BigDecimal.ZERO) != 0 || room.getAgreement().getRentBeginDate().before(prevMeter.getCheckTime())) && room.getAgreement().getRentBeginDate().before(thisMeter.getCheckTime())) {
					daChargeItemService.createMeterChargeItem(feeRule, null);
				}
			}
		} else if (suite.getRentType() == 1) {// 分租
			DaFeeRule suiteMatchedFeeRule = null;
			for (DaFeeRule suiteFeeRule : suite.getFeeRules()) {
				if (suiteFeeRule.getFeeRuleCfg().equals(feeRule.getFeeRuleCfg())) {
					suiteMatchedFeeRule = suiteFeeRule;
					break;
				}
			}

			if (suiteMatchedFeeRule == null) {// 只有子表，没有主表，不涉及分摊，抄完一个表即开始计费
				DaRoom room = feeRule.getRoom();
				if (room == null) {
					return;
				}

				if (room.getAgreement() != null && room.getAgreement().getRentBeginDate() != null
						&& feeRule.getMeters().size() > 1) {
					DaMeter prevMeter = feeRule.getMeters().get(1);
					DaMeter thisMeter = feeRule.getMeters().get(0);
					if ((prevMeter.getCount().compareTo(BigDecimal.ZERO) != 0 || room.getAgreement().getRentBeginDate().before(prevMeter.getCheckTime())) && room.getAgreement().getRentBeginDate().before(thisMeter.getCheckTime())) {
						List<DaFeeRule> matchedFeeRules = new ArrayList<DaFeeRule>();
						matchedFeeRules.add(feeRule);
						daChargeItemService.createMeterChargeItem(null, matchedFeeRules);
					}
				}
			} else { // 有主表，
				List<DaFeeRule> matchedFeeRules = new ArrayList<DaFeeRule>();
				boolean hasRoomRent = false;
				for (DaRoom room : suite.getRooms()) {
					if (room.getAgreement() != null && room.getAgreement().getRentBeginDate() != null) {
						for (DaFeeRule roomFeeRule : room.getFeeRules()) {
							if (roomFeeRule.getFeeRuleCfg().equals(feeRule.getFeeRuleCfg())) {
								matchedFeeRules.add(roomFeeRule);
							}
						}
						hasRoomRent = true;
					}
				}
				if (!hasRoomRent) {
					return ;
				}
				if (matchedFeeRules.size() == 0) {// 只有主表，没有子表，不涉及公摊
					if (suite.getRentRooms().size() == 0) {
						return;
					}
					DaRoom room = suite.getRentRooms().get(0);
					if (room.getAgreement() != null && room.getAgreement().getRentBeginDate() != null && feeRule.getMeters().size() > 1) {
						DaMeter prevMeter = feeRule.getMeters().get(1);
						DaMeter thisMeter = feeRule.getMeters().get(0);
						if ((prevMeter.getCount().compareTo(BigDecimal.ZERO) != 0 || room.getAgreement().getRentBeginDate().before(prevMeter.getCheckTime())) && room.getAgreement().getRentBeginDate().before(thisMeter.getCheckTime())) {
							daChargeItemService.createMeterChargeItem(feeRule, null);
						}
					}
				} else {// 既有主表，又有子表，涉及公摊
					boolean needCreateChargeItem = true;
					boolean suiteNeedCreateChargeItem = false;
					genericService.refresh(suiteMatchedFeeRule);
					if (suiteMatchedFeeRule.getChargeItems() == null || suiteMatchedFeeRule.getChargeItems().size() == 0) {
						Date earliestRentBeginDate = matchedFeeRules.get(0).getRoom().getAgreement().getRentBeginDate();
						for (DaFeeRule roomFeeRule : matchedFeeRules) {
							if (roomFeeRule.getRoom().getAgreement().getRentBeginDate().before(earliestRentBeginDate)) {
								earliestRentBeginDate = roomFeeRule.getRoom().getAgreement().getRentBeginDate(); 
							}
						}
						
						if (suiteMatchedFeeRule.getMeters() != null && suiteMatchedFeeRule.getMeters().size() > 1 && suiteMatchedFeeRule.getMeters().get(1).getCheckTime().compareTo(earliestRentBeginDate) >= 0) {
							suiteNeedCreateChargeItem=true;
						}
					} else {
						if (suiteMatchedFeeRule.getMeters() != null && suiteMatchedFeeRule.getMeters().size() > 1 && suiteMatchedFeeRule.getMeters().get(1).getCheckTime().compareTo(suiteMatchedFeeRule.getChargeItems().get(0).getDateEndRecv()) >= 0) {
							suiteNeedCreateChargeItem = true;
						}
					}
					if (!suiteNeedCreateChargeItem) {
						return;
					}
					
					for (DaFeeRule roomFeeRule : matchedFeeRules) {
						if (roomFeeRule.getChargeItems() ==  null || roomFeeRule.getChargeItems().size() == 0) {
							if (roomFeeRule.getMeters() != null && roomFeeRule.getMeters().size() > 1) {
								DaMeter prevMeter = roomFeeRule.getMeters().get(1);
								if (!roomFeeRule.getRoom().getAgreement().getRentBeginDate()
										.before(prevMeter.getCheckTime())) {// 抄表时间在合约开始时间之后，否则不产生费用
									needCreateChargeItem = false;
									break;
								}
							} else {
								needCreateChargeItem = false;
								break;
							}
						} else {
							if (roomFeeRule.getMeters() != null && roomFeeRule.getMeters().size() > 1) {
								DaMeter prevMeter = roomFeeRule.getMeters().get(1);
								if (!roomFeeRule.getRoom().getAgreement().getRentBeginDate().before(prevMeter.getCheckTime()) || prevMeter.getCheckTime().before(roomFeeRule.getChargeItems().get(0).getDateEndRecv())) {// 抄表时间在合约开始时间之后，否则不产生费用
									needCreateChargeItem = false;
									break;
								}
							}
						}
					}
					
					if (needCreateChargeItem) {
						daChargeItemService.createMeterChargeItem(suiteMatchedFeeRule, matchedFeeRules);
					}
				}
			}
		}
	}

	@Transactional
	@Rest(type = "update")
	public Meter update(Meter model) {
		BigDecimal price = genericService.load(model.getFeeRule()).getFeeRuleCfg().getFeeRuleCfgCalc().getPrice();
		model.setPrice(price);
		return genericService.update(model);
	}

	/**
	 * 根据房间的费用配置规则，查询对应的仪表刻度集合
	 * 
	 * @param feeRuleId
	 * @return
	 */
	@Rest(type = "search")
	public List<Meter> searchMeterByFeeRule(Integer feeRuleId) {
		List<Meter> meters = new ArrayList<>();
		FeeRule feeRule = new FeeRule();
		feeRule.setId(feeRuleId);
		feeRule = genericService.load(feeRule);
		if (feeRule != null) {
			meters = feeRule.getMeters();
		}
		// 显示前10条抄表记录
		if (meters.size() >= 10) {
			meters = meters.subList(0, 10);
		}
		for (Meter meter : meters) {
			if (isBeRelated(meter.getId())) {
				meter.setDeletable(false);
			} else {
				meter.setDeletable(true);
			}
		}

		return meters;
	}

	/**
	 * 查看该meterId是否被FeeAddition关联了
	 * 
	 * @param meterId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private boolean isBeRelated(Integer meterId) {
		boolean bResult = false;
		String ql = "select a from " + FeeAddition.class.getName() + " a where a.meter1.id = ? or a.meter2.id = ? ";
		List<Object> lstParams = new ArrayList<>();
		lstParams.add(meterId);
		lstParams.add(meterId);
		PageInfo<FeeAddition> pageInfos = genericService.searchByQl(new QLInfo(ql, lstParams), false);
		if (pageInfos.getData() != null && pageInfos.getData().size() > 0) {
			bResult = true;
		}

		return bResult;
	}

	/**
	 * 删除抄表，同时要删除未收费的费用项
	 * 
	 * @param model
	 * @return
	 */
	@Rest(type = "delete")
	public boolean deleteMeter(DaMeter model) {

		DaMeter meter = genericService.load(model);
		DaChargeItem chargeItemModel = new DaChargeItem();
		chargeItemModel.setMeter2(meter);

		DaChargeItem deletedChargeItem = null;
		List<DaChargeItem> chargeItems = genericService.searchByModel(chargeItemModel, Condition.DEFAULT).getData();
		if (chargeItems != null && chargeItems.size() > 0) {
			for (DaChargeItem daChargeItem : chargeItems) {
				if (daChargeItem.getChargeBill() == null) {
					deletedChargeItem = daChargeItem;
					break;
				} else {
					throw new ApplicationException("该抄表所产生的费用已经生成账单，无法删除！");
				}
			}
		}

		boolean oneHasChargeBill = false;
		DaSuite relatedSuite = null;
		if (deletedChargeItem == null) { //抄表并未生成chargeItem，直接删除
			return genericService.delete(meter);
		}
		if (deletedChargeItem.getRoom() != null) {
			relatedSuite = deletedChargeItem.getRoom().getSuite();
		} else {
			relatedSuite = deletedChargeItem.getSuite();
		}
		if (deletedChargeItem != null && relatedSuite.getRentType() == 1) {// 分租
			FeeRuleCfg relatedFeeRuleCfg = deletedChargeItem.getFeeRuleCfg();
			// check whether there is a same feerulecfg in suite feerules so
			// that we need deleted related chargeItems in other room in that
			// suite
			DaFeeRule matchedSuiteFeeRule = null;
			for (DaFeeRule feeRule : relatedSuite.getFeeRules()) {
				if (feeRule.getFeeRuleCfg().equals(relatedFeeRuleCfg)) {
					matchedSuiteFeeRule = feeRule;
					break;
				}
			}
			if (matchedSuiteFeeRule != null) {
				for (DaRoom room : relatedSuite.getRentRooms()) {
					if (oneHasChargeBill) {
						break;
					}
					for (DaFeeRule feeRule : room.getFeeRules()) {
						if (feeRule.getFeeRuleCfg().equals(relatedFeeRuleCfg)) {
							if (feeRule.getChargeItems().get(0).getChargeBill() != null) {
								oneHasChargeBill = true;
								break;
							}
						}
					}
				}

				if (!oneHasChargeBill) {
					for (DaRoom room : relatedSuite.getRentRooms()) {
						for (DaFeeRule feeRule : room.getFeeRules()) {
							if (feeRule.getFeeRuleCfg().equals(relatedFeeRuleCfg)) {
								DaChargeItem needDeleteChargeItem = feeRule.getChargeItems().get(0);
								genericService.delete(needDeleteChargeItem);
								break;
							}
						}
					}
					if (matchedSuiteFeeRule.getChargeItems().size() != 0) {
						genericService.delete(matchedSuiteFeeRule.getChargeItems().get(0));//suite不会产生费用，直接删除
					}
				}
			}
		}
		if (!oneHasChargeBill && genericService.load(deletedChargeItem) != null) {
			genericService.delete(deletedChargeItem);
		}
		if (!oneHasChargeBill) {
			return genericService.delete(meter);
		}else {
			throw new ApplicationException("该抄表所产生的费用已经生成账单，无法删除！");
		}

	}

	/**
	 * 根据仪表查询房源
	 * 
	 * @param feeRuleCfgId
	 * @return
	 */
	@Rest(type = "search")
	public List<DaFeeRule> searchMeterWithSuite(Integer feeRuleCfgId) {
		List<DaFeeRule> feeRules = new ArrayList<>();
		DaSuite suite = genericService.load(DaSuite.class, feeRuleCfgId);
		if (suite != null && suite.getFeeRules() != null) {
			int today = Calendar.getInstance().get(Calendar.DAY_OF_YEAR);
			for (DaFeeRule daFeeRule : suite.getFeeRules()) {
				if (daFeeRule.getFeeRuleCfg().getFeeRuleCfgDesc().getType() == FeeRuleType.meter) {
					feeRules.add(daFeeRule);
					List<DaMeter> lstMeter = daFeeRule.getMeters();
					if (lstMeter == null || lstMeter.size() == 0) {
						// 初始化表刻度
						DaMeter initMeter = new DaMeter();
						initMeter.setCount(BigDecimal.valueOf(0));
						initMeter.setFeeRule(daFeeRule);
						initMeter.setCheckTime(null);
						daFeeRule.setLastMeter(initMeter);
					} else if (lstMeter.size() >= 1) {
						DaMeter meter = daFeeRule.getMeter(0);
						Calendar checkTime = Calendar.getInstance();
						checkTime.setTime(meter.getCheckTime());
						// 判断抄表是否为本次收费周期
						boolean isCurrentMonthMeter = false;
						FeeRuleCfg feeRuleCfg = daFeeRule.getFeeRuleCfg();
						if (feeRuleCfg != null) {
							FeeRuleCfgCalc feeRuleCfgCalc = feeRuleCfg.getFeeRuleCfgCalc();
							if (feeRuleCfgCalc.getRentCycleType() == 0) {// 按月
								isCurrentMonthMeter = today
										- checkTime.get(Calendar.DAY_OF_YEAR) < feeRuleCfgCalc.getRentCycle() * 30;
							}
						}
						if (isCurrentMonthMeter) {
							daFeeRule.setCurrentMeter(meter);
							if (lstMeter.size() >= 2) {
								daFeeRule.setLastMeter(daFeeRule.getMeter(1));
								if (lstMeter.size() >= 3) {
									daFeeRule.setLastLastMeter(daFeeRule.getMeter(2));
								}
							} else {
								DaMeter initMeter = new DaMeter();
								initMeter.setCount(BigDecimal.valueOf(0));
								initMeter.setFeeRule(daFeeRule);
								initMeter.setCheckTime(null);
								daFeeRule.setLastMeter(initMeter);
							}

						} else {
							daFeeRule.setLastMeter(meter);
							if (lstMeter.size() >= 2) {
								daFeeRule.setLastLastMeter(daFeeRule.getMeter(1));
							}
						}
					}
				}
			}
		}
		return feeRules;
	}

	/**
	 * 根据仪表查询房源
	 * 
	 * @param buildingId
	 * @param feeRuleCfgId
	 * @return
	 */
	@Rest(type = "search")
	public List<DaSuite> searchSuiteWithMeter(Integer feeRuleCfgId) {

		// 已抄表: room.feeRule.meter
		DaSuite model = new DaSuite();
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		model.setLandlordUser(landlordUser.getOwnerUser());
		// 表类型
		// ModelUtil.setProperty(model, "feeRule.feeRuleCfg.feeRuleCfgDesc.id",
		// meterTypeId);
		PageInfo<DaSuite> pageInfo = genericService.searchAll(model);
		int today = Calendar.getInstance().get(Calendar.DAY_OF_YEAR);
		List<DaSuite> daSuites = new ArrayList<DaSuite>();
		for (DaSuite daSuite : pageInfo.getData()) {
			DaFeeRule matchedFeeRule = null;
			for (DaFeeRule feeRule : daSuite.getFeeRules()) {
				if (feeRule != null && feeRule.getFeeRuleCfg() != null
						&& feeRule.getFeeRuleCfg().getFeeRuleCfgDesc() != null) {
					if (feeRuleCfgId.equals(feeRule.getFeeRuleCfg().getFeeRuleCfgDesc().getId())) {
						matchedFeeRule = feeRule;
						break;
					}
				}
			}
			if (matchedFeeRule != null) {
				List<DaMeter> lstMeter = matchedFeeRule.getMeters();

				if (lstMeter == null || lstMeter.size() == 0) {
					// 初始化表刻度
					DaMeter initMeter = new DaMeter();
					initMeter.setCount(BigDecimal.valueOf(0));
					initMeter.setFeeRule(matchedFeeRule);
					initMeter.setCheckTime(null);
					daSuite.setLastMeter(initMeter);
					daSuites.add(daSuite);
				} else if (lstMeter.size() >= 1) {
					DaMeter meter = matchedFeeRule.getMeter(0);
					Calendar checkTime = Calendar.getInstance();
					checkTime.setTime(meter.getCheckTime());
					// 判断抄表是否为本次收费周期
					boolean isCurrentMonthMeter = false;
					FeeRuleCfg feeRuleCfg = matchedFeeRule.getFeeRuleCfg();
					if (feeRuleCfg != null) {
						FeeRuleCfgCalc feeRuleCfgCalc = feeRuleCfg.getFeeRuleCfgCalc();
						if (feeRuleCfgCalc.getRentCycleType() == 0) {// 按月
							isCurrentMonthMeter = today
									- checkTime.get(Calendar.DAY_OF_YEAR) < feeRuleCfgCalc.getRentCycle() * 30;
						}
					}
					if (isCurrentMonthMeter) {
						daSuite.setCurrentMeter(meter);
						if (lstMeter.size() >= 2) {
							daSuite.setLastMeter(matchedFeeRule.getMeter(1));
							if (lstMeter.size() >= 3) {
								daSuite.setLastLastMeter(matchedFeeRule.getMeter(2));
							}
						} else {
							DaMeter initMeter = new DaMeter();
							initMeter.setCount(BigDecimal.valueOf(0));
							initMeter.setFeeRule(matchedFeeRule);
							initMeter.setCheckTime(null);
							daSuite.setLastMeter(initMeter);
						}

						daSuites.add(daSuite);
					} else {
						daSuite.setLastMeter(meter);
						if (lstMeter.size() >= 2) {
							daSuite.setLastLastMeter(matchedFeeRule.getMeter(1));
						}
						daSuites.add(daSuite);
					}
				}
			}
		}
		return daSuites;
	}

	/**
	 * 获取仪表
	 * 
	 * @return
	 */
	@Rest(type = "search")
	public List<FeeRuleCfgDesc> showMeterFeeRuleCfg() {
		FeeRuleCfgDesc feeRuleCfgDesc = new FeeRuleCfgDesc();
		feeRuleCfgDesc.setType(FeeRuleType.meter);
		feeRuleCfgDesc.setIsShare(false);

		// List<FeeRuleCfgDesc> undesc =
		// daRoomMeterItemService.showMeterFeeRuleCfg();

		List<FeeRuleCfgDesc> desc = feeRuleCfgDescService.searchAllDesc(feeRuleCfgDesc);
		/*
		 * for (int i = 0; i < undesc.size(); i++) {
		 * System.out.println(undesc.get(i).getName()); desc.add(undesc.get(i));
		 * }
		 */

		return desc;
	}

	@Rest(type = "search")
	public List<FeeRuleCfg> showMeterFeeRuleCfgForSuite(Integer suiteId) {
		Set<FeeRuleCfg> set = new LinkedHashSet<FeeRuleCfg>();
		DaSuite suite = genericService.load(DaSuite.class, suiteId);
		if (suite != null && suite.getFeeRules() != null) {
			for (DaFeeRule daFeeRule : suite.getFeeRules()) {
				FeeRuleCfg feeRuleCfg = daFeeRule.getFeeRuleCfg();
				if (feeRuleCfg != null && feeRuleCfg.getFeeRuleCfgDesc().getType() == FeeRuleType.meter) {
					set.add(feeRuleCfg);
				}
			}

			for (DaRoom room : suite.getRooms()) {
				for (DaFeeRule daFeeRule : room.getFeeRules()) {
					FeeRuleCfg feeRuleCfg = daFeeRule.getFeeRuleCfg();
					if (feeRuleCfg != null && feeRuleCfg.getFeeRuleCfgDesc().getType() == FeeRuleType.meter) {
						set.add(feeRuleCfg);
					}
				}
			}
		}
		return new ArrayList<FeeRuleCfg>(set);
	}

	/**
	 * 查看抄表详情
	 * 
	 * @param room
	 * @return
	 */
	@Rest(type = "search")
	public List<DaMeter> getSuiteMeters(DaFeeRule model) {

		DaFeeRule feeRule = genericService.load(model);

		List<DaMeter> meters = feeRule.getMeters();
		if (meters != null && meters.size() > 0) {
			DaMeter lastMeter = meters.get(0);
			DaChargeItem chargeItemModel = new DaChargeItem();
			chargeItemModel.setMeter2(lastMeter);
			if (isCanDeleteChargeItem(chargeItemModel)) {
				lastMeter.setDeletable(true);
			}
		}
		return meters;
	}

	/**
	 * 是否能删除对应的收费项
	 * 
	 * @param model
	 * @return
	 */
	public boolean isCanDeleteChargeItem(DaChargeItem model) {
		boolean bresult = true;
		List<DaChargeItem> chargeItems = genericService.searchByModel(model, Condition.DEFAULT).getData();
		if (chargeItems != null && chargeItems.size() > 0) {
			for (DaChargeItem daChargeItem : chargeItems) {
				if (daChargeItem.getChargeBill() != null) {
					bresult = false;
				}
			}
		}
		return bresult;
	}

	private List<Date> getCategoriesInDate(Integer suiteId, Integer feeRuleCfgId) {
		Calendar oneYearAgoDate = Calendar.getInstance();
		oneYearAgoDate.add(Calendar.YEAR, -1);
		QLInfo qlInfo = new QLInfo("select distinct a.createChargeTime from DaChargeItem a where a.feeRule.feeRuleCfg.id = ? and (a.suite.id = ? or a.room.suite.id = ?) and a.createChargeTime > ? order by a.createChargeTime asc",false,feeRuleCfgId, suiteId, suiteId,oneYearAgoDate.getTime());
		List<Date> dates = genericService.searchByQl(qlInfo).getData();
		return dates;
	}
	/**
	 * 获取按房间及费用规则显示抄表明细图表的横坐标
	 * 
	 * @param feeRuleId
	 * @return
	 */
	@Rest(type = "search")
	public Object[] getCategories(Integer suiteId, Integer feeRuleCfgId) {
		
		List<String> categories = new ArrayList<>();
		List<Date> dates = getCategoriesInDate(suiteId, feeRuleCfgId);
		for (Date d : dates) {
			categories.add(DateTimeUtil.formatDateTime(d,DateTimeUtil.ISO_DATE_FORMAT));
		}
		return categories.toArray();
		
		/*DaSuite dbSuite = genericService.load(DaSuite.class, suiteId);
		FeeRuleCfg dbFeeRuleCfg = genericService.load(FeeRuleCfg.class, feeRuleCfgId);
		if (dbSuite == null || dbFeeRuleCfg == null) {
			return categories.toArray();
		}
		
		DaFeeRule matchedFeeRule = null;
		for (DaFeeRule feeRule : dbSuite.getFeeRules()) {
			if (feeRule.getFeeRuleCfg().equals(dbFeeRuleCfg)) {
				matchedFeeRule = feeRule;
			}
		}
		
		if(matchedFeeRule == null) {
			return categories.toArray();
		}
		
		List<DaChargeItem> chargeItems = matchedFeeRule.getChargeItems();
		Calendar oneYearAgoDate = Calendar.getInstance();
		oneYearAgoDate.add(Calendar.YEAR, -1);
		for (int i=chargeItems.size()-1; i>=0; i--) {
			if (chargeItems.get(i).getMeter2().getCheckTime().after(oneYearAgoDate.getTime())) {
				categories.add(DateTimeUtil.formatDateTime(chargeItems.get(i).getMeter2().getCheckTime(),DateTimeUtil.ISO_DATE_FORMAT));
			}
		}
		return categories.toArray();*/
	}

	private Object[] getMeterTimesRecordCount(DaFeeRule matchedFeeRule, List<Date> categoriesDate, boolean addZero) throws ParseException {
		//addZero = true;
		List<BigDecimal> counts = new ArrayList<BigDecimal>();
		
		if (categoriesDate.size() == 0) {
			return counts.toArray();
		}
		List<DaChargeItem> chargeItems = matchedFeeRule.getChargeItems();
		Calendar oneYearAgoDate = Calendar.getInstance();
		oneYearAgoDate.add(Calendar.YEAR, -1);
		
		int i = 0;
		Calendar categoryDate = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		categoryDate.setTime(categoriesDate.get(i));
		
		
		for (int j = chargeItems.size() - 1; j >= 0; j--) {
			
			Calendar createChargeDate = Calendar.getInstance();
			createChargeDate.setTime(chargeItems.get(j).getCreateChargeTime());
			
			if (categoryDate.compareTo(createChargeDate) < 0) {
				if ( addZero ) {
					counts.add(BigDecimal.valueOf(0));
				}else {
					counts.add(null);
				}
				
				i++;
				if (i<categoriesDate.size()) {
					categoryDate.setTime(categoriesDate.get(i));
				} else {
					break;
				}
				j++;
			} else if (categoryDate.compareTo(createChargeDate) == 0) {
				counts.add(chargeItems.get(j).getMeter2().getCount().subtract(chargeItems.get(j).getMeter1().getCount()));
				i++;
				if (i<categoriesDate.size()) {
					categoryDate.setTime(categoriesDate.get(i));
				} else {
					break;
				}
			} else {
				continue;
			}
		
		}
		while (i++ < categoriesDate.size()) {
			if ( addZero ) {
				counts.add(BigDecimal.valueOf(0));
			}else {
				counts.add(null);
			}
		}
		return counts.toArray();
	}

	/**
	 * 系统模块统计分析
	 * 
	 * @param type
	 * @param year
	 * @return
	 * @throws ParseException 
	 */
	@Rest(type = "search")
	public Map<String, Object []> analyse(Integer suiteId, Integer feeRuleCfgId) throws ParseException {
		DaSuite dbSuite = genericService.load(DaSuite.class, suiteId);
		FeeRuleCfg dbFeeRuleCfg = genericService.load(FeeRuleCfg.class, feeRuleCfgId);
		Map<String, Object []> result =ListOrderedMap.decorate(new HashMap<String, Object []>());
		
		List<Date> categoriesDate = getCategoriesInDate(suiteId, feeRuleCfgId);
		if(dbSuite == null || dbFeeRuleCfg == null) {
			return result;
		}
		
		boolean addZero = false;
		for (DaFeeRule feeRule : dbSuite.getFeeRules()) {
			if (feeRule.getFeeRuleCfg().equals(dbFeeRuleCfg)) {
				result.put(dbSuite.getName(), getMeterTimesRecordCount(feeRule, categoriesDate, addZero));
				addZero = true;
				break;
			}
		}
		
		for (DaRoom room : dbSuite.getRooms()) {
			for (DaFeeRule feeRule : room.getFeeRules()) {
				if (feeRule.getFeeRuleCfg().equals(dbFeeRuleCfg)) {
					result.put(room.getName() + "（" +dbSuite.getName() + "）", getMeterTimesRecordCount(feeRule, categoriesDate, addZero));
					break;
				}
			}
		}
		return result;
	}
}
